; FileCore responses to MultiFS format service requests

; These are expected to be called only by FileCore's base incarnation


; entry: r1 = Service_EnumerateFormats
;        r2 = pointer to list of formats so far
;        SB *invalid*


; exit:
;   error:
;        r0 = error pointer
;        r1 = Service_Serviced
;   no error:
;        r1 unchanged (still Service_EnuerateFormats)
;        r2 updated to point to the extended list

FileCoreService_EnumerateFormats ROUT
        Push    "r0-r11,lr"
        MOV     r11, r2

        SUB     sp, sp, #16
        MOV     r0, sp
        baddr   r1, message_filename
        MOV     r2, #0
        SWI     XMessageTrans_OpenFile
        BVS     %FT90

        ADR     r10, EnumFormats
        B       %FT20

10
        ; Claim an RMA block for the format
        MOV     r3, #SzEnumFormatsBlock
        MOV     r0, #ModHandReason_Claim
        SWI     XOS_Module
        BVS     %FT80

        ; Zero out 2 string links
        MOV     lr, #0
        STR     lr, [r2, #EnumFormats_MenuString]
        STR     lr, [r2, #EnumFormats_MenuHelp]

        ; Copy the SWI fields across
        LDR     lr, [r10, #0*4]
        STR     lr, [r2, #EnumFormats_Flags]
        LDR     lr, =XFileCore_DiscFormat
        STR     lr, [r2, #EnumFormats_DiscFormatSWI]
        LDR     lr, [r10, #1*4]
        STR     lr, [r2, #EnumFormats_DiscFormatParam]
        LDR     lr, [r10, #2*4]
        STR     lr, [r2, #EnumFormats_LayoutStructureSWI]
        LDR     lr, [r10, #3*4]
        ADRL    r0, Module_BaseAddr
        ADD     lr, lr, r0
        STR     lr, [r2, #EnumFormats_LayoutStructureParam]

        ; Link block to chain
        STR     r11, [r2, #EnumFormats_Link]
        MOV     r11, r2

        ; Claim 1st string
        ADD     r1, r10, #4*4
        BL      %FT95
        STRVC   r1, [r11, #EnumFormats_MenuString]

        ; Advance to 2nd string
        ADDVC   r1, r10, #4*4
        BLVC    strlen
        ADDVC   r3, r3, #1
        ADDVC   r1, r1, r3

        ; Get values to advance to next block
        MOVVC   r2, r1
        BLVC    strlen
        ADDVC   r3, r3, #1

        ; Copy 2nd string
        BLVC    %FT95
        STRVC   r1, [r11, #EnumFormats_MenuHelp]
        BVS     %FT80

        ; Advance to format descriptor
        ADD     r10, r2, r3
        STR     r10, [r11, #EnumFormats_FormatParam]
        ADD     r10, r10, #3+2
        BIC     r10, r10, #3

20
        ; End of list?
        LDR     lr, [r10]
        TEQ     lr, #0
        BNE     %BT10

80
        Push    "r0"
        ADD     r0, sp, #4
        SWI     XMessageTrans_CloseFile
        STRVS   r0, [sp]
        Pull    "r0"

90
        ADD     sp, sp, #16

        MOVVS   lr, #Service_Serviced
        STRVS   lr, [sp, #1*4]
        STRVS   r0, [sp]

        STR     r11, [sp, #2*4]         ; returned r2

        Pull    "r0-r11, pc",,^

; entry r1 -> message tag
; exit  r0 trashed or error
;       r1 -> RMA block containing looked-up message or error
95
        Push    "r2-r7,lr"
        ADD     r0, sp, #7*4            ; MessageTrans block on stack
        MOV     r2, #0
        MOV     r3, #0
        MOV     r4, #0
        MOV     r5, #0
        MOV     r6, #0
        MOV     r7, #0
        SWI     XMessageTrans_Lookup
        MOVVC   r1, r2
        ADDVC   r3, r3, #1
        MOVVC   r0, #ModHandReason_Claim
        SWIVC   XOS_Module
        Swap    r1, r2, VC
        BLVC    strcpy
        Pull    "r2-r7,pc"

EnumFormats
        DCD     EnumFormats_IsNative :OR: EnumFormats_HasFormatParam
        DCD     Format_Floppy :OR: Format_L
        DCD     XFileCore_LayoutStructure
        DCD     Format_LFloppyDiscRecord - Module_BaseAddr
LFormat_DescribeTag
        DCB     "FS0",0         ; Format description for a menu
        DCB     "FS1",0         ; accompanying !help
        DCB     "L",0
        ALIGN

        DCD     EnumFormats_IsNative :OR: EnumFormats_HasFormatParam
        DCD     Format_Floppy :OR: Format_D
        DCD     XFileCore_LayoutStructure
        DCD     Format_DFloppyDiscRecord - Module_BaseAddr
DFormat_DescribeTag
        DCB     "FS2", 0
        DCB     "FS3", 0
        DCB     "D",0
        ALIGN

        DCD     EnumFormats_IsNative :OR: EnumFormats_HasFormatParam
        DCD     Format_Floppy :OR: Format_E
        DCD     XFileCore_LayoutStructure
        DCD     Format_EFloppyDiscRecord - Module_BaseAddr
EFormat_DescribeTag
        DCB     "FS4",0
        DCB     "FS5", 0
        DCB     "E",0
        ALIGN

        DCD     EnumFormats_IsNative :OR: EnumFormats_HasFormatParam
        DCD     Format_Floppy :OR: Format_F
        DCD     XFileCore_LayoutStructure
        DCD     Format_FFloppyDiscRecord - Module_BaseAddr
FFormat_DescribeTag
        DCB     "FS6", 0
        DCB     "FS7", 0
        DCB     "F",0
        ALIGN

        DCD     EnumFormats_IsNative :OR: EnumFormats_HasFormatParam
        DCD     Format_Floppy :OR: Format_G
        DCD     XFileCore_LayoutStructure
        DCD     Format_GFloppyDiscRecord - Module_BaseAddr
GFormat_DescribeTag
        DCB     "FS9", 0
        DCB     "FS10", 0
        DCB     "G",0
        ALIGN

        DCD     0

Format_LFloppyDiscRecord
        ; * means gets filled in before being used
        DCB     8       ; Log2 Sector Size
        DCB     16      ; sectors per track
        DCB     1       ; Heads (adjusted)
        DCB     Double  ; Density
        DCB     0       ; Length of Id field
        DCB     0       ; Bytes per map bit
        DCB     0       ; Side/Side sector skew
        DCB     0       ; Boot option
        DCB     SequenceSides
        DCB     0       ; Zones
        DCW     0       ; ZoneSpare
        DCD     L_Root  ; Root dir disc address
        DCD     640*1024 ; Disc size
        DCW     0       ; DiscId *
        DCB     "          " ; DiscName *
        ASSERT  ({PC} - Format_LFloppyDiscRecord) = DiscRecSig

Format_DFloppyDiscRecord
        ; * means gets filled in before being used
        DCB     10      ; Log2 Sector Size
        DCB     5       ; sectors per track
        DCB     2       ; Heads
        DCB     Double  ; Density
        DCB     0       ; Length of Id field
        DCB     0       ; Bytes per map bit
        DCB     0       ; Side/Side sector skew
        DCB     0       ; Boot option
        DCB     0       ; Neither sequence sides nor double step
        DCB     0       ; Zones
        DCW     0       ; ZoneSpare
        DCD     D_Root  ; Root dir disc address
        DCD     800*1024 ; Disc size
        DCW     0       ; DiscId *
        DCB     "          " ; DiscName *
        ASSERT  ({PC} - Format_DFloppyDiscRecord) = DiscRecSig

Format_EFloppyDiscRecord
        ; * means gets filled in before being used
        DCB     10      ; Log2 Sector Size
        DCB     5       ; sectors per track
        DCB     2       ; Heads
        DCB     Double  ; Density
        DCB     15      ; Length of Id field (map bits)
        DCB     7       ; Bytes per map bit
        DCB     1       ; Side/Side sector skew
        DCB     0       ; Boot option
        DCB     0       ; Neither sequence sides nor double step
        DCB     1       ; Zone
        DCW     &520    ; ZoneSpare
        DCD     NewMapRoot ; Root dir ind. disc address
        DCD     800*1024 ; Disc size
        DCW     0       ; DiscId *
        DCB     "          " ; DiscName *
        ASSERT  ({PC} - Format_EFloppyDiscRecord) = DiscRecSig

Format_FFloppyDiscRecord
        ; * means gets filled in before being used
        DCB     10      ; Log2 Sector Size
        DCB     10      ; sectors per track
        DCB     2       ; Heads
        DCB     Quad    ; Density
        DCB     15      ; Length of Id field (map bits)
        DCB     6       ; Bytes per map bit
        DCB     1       ; Side/Side sector skew
        DCB     0       ; Boot option
        DCB     0       ; Neither sequence sides nor double step
        DCB     4       ; Zone
        DCW     1600    ; ZoneSpare
        DCD     &209    ; Root dir ind. disc address
        DCD     1600*1024 ; Disc size
        DCW     0       ; DiscId *
        DCB     "          " ; DiscName *
        ASSERT  ({PC} - Format_FFloppyDiscRecord) = DiscRecSig

Format_GFloppyDiscRecord
        ; * means gets filled in before being used
        DCB     10      ; Log2 Sector Size
        DCB     20      ; sectors per track
        DCB     2       ; Heads
        DCB     Octal   ; Density
        DCB     15      ; Length of Id field (map bits)
        DCB     6       ; Bytes per map bit
        DCB     1       ; Side/Side sector skew
        DCB     0       ; Boot option
        DCB     0       ; Neither sequence sides nor double step
        DCB     7       ; Zone
        DCW     800     ; ZoneSpare
        DCD     &20f    ; Root dir ind. disc address
        DCD     3200*1024 ; Disc size
        DCW     0       ; DiscId *
        DCB     "          " ; DiscName *
        ASSERT  ({PC} - Format_GFloppyDiscRecord) = DiscRecSig

FileCoreService_IdentifyFormat ROUT
        Push    "r2,lr"

        LDRB    r2, [r0, #0]
        TEQ     r2, #0
        Pull    "r2,pc",EQ,^            ; Length 0

        TEQ     r2, #"L"
        TEQNE   r2, #"l"
        TEQNE   r2, #"D"
        TEQNE   r2, #"d"
        TEQNE   r2, #"E"
        TEQNE   r2, #"e"
        TEQNE   r2, #"F"
        TEQNE   r2, #"f"
        TEQNE   r2, #"G"
        TEQNE   r2, #"g"
        Pull    "r2,pc",NE,^            ; Doesn't start L, D, E or F

        LDRB    r2, [r0, #1]
        TEQ     r2, #0
        Pull    "r2,pc",NE,^            ; Length > 1

        ; Determine which it is
        LDRB    r2, [r0, #0]
        TEQ     r2, #"L"
        TEQNE   r2, #"l"
        MOVEQ   r3, #Format_Floppy :OR: Format_L
        ADREQ   r5, Format_LFloppyDiscRecord
        TEQ     r2, #"D"
        TEQNE   r2, #"d"
        MOVEQ   r3, #Format_Floppy :OR: Format_D
        ADREQ   r5, Format_DFloppyDiscRecord
        TEQ     r2, #"E"
        TEQNE   r2, #"e"
        MOVEQ   r3, #Format_Floppy :OR: Format_E
        ADREQ   r5, Format_EFloppyDiscRecord
        TEQ     r2, #"F"
        TEQNE   r2, #"f"
        MOVEQ   r3, #Format_Floppy :OR: Format_F
        ADREQ   r5, Format_FFloppyDiscRecord
        TEQ     r2, #"G"
        TEQNE   r2, #"g"
        MOVEQ   r3, #Format_Floppy :OR: Format_G
        ADREQ   r5, Format_GFloppyDiscRecord

        LDR     r2, =XFileCore_DiscFormat
        LDR     r4, =XFileCore_LayoutStructure

        ; Claim service and return
        MOV     r1, #Service_Serviced
        ADD     sp, sp, #1*4
        Pull    "pc",,^

FileCoreService_DisplayFormatHelp ROUT
        Push    "r0-r7,lr"

        SUB     sp, sp, #16+1024        ; Message block and buffer

        ; Open the message file
        MOV     r0, sp
        ADRL    r1, message_filename
        MOV     r2, #0
        SWI     XMessageTrans_OpenFile
        BVS     %FT90

        ; Lookup the message
        MOV     r0, sp
        ADR     r1, FormatHelp
        ADD     r2, sp, #16
        MOV     r3, #1024
        MOV     r4, #0
        MOV     r5, #0
        MOV     r6, #0
        MOV     r7, #0
        SWI     XMessageTrans_GSLookup
        BVS     %FT80

        ; Write it out
        MOV     r0, r2
        MOV     r1, r3
        SWI     XOS_WriteN 

80
        ; Close the message file, preserving the error
        MOV     r9, #0
        MOVVS   r9, r0
        MOV     r0, sp
        SWI     XMessageTrans_CloseFile
        MOVVS   r9, r0
        MOVS    r0, r9
        MOVNE   lr, pc
        ORRNE   lr, lr, #V_bit
        TEQNEP  pc, lr
90
        ; Drop the stack frame and return error if generated.
        ADD     sp, sp, #16+1024
        STRVS   r0, [sp, #0*4]
        MOVVS   r1, #Service_Serviced
        STRVS   r1, [sp, #1*4]
        Pull    "r0-r7,pc",,^

FormatHelp
        DCB     "FS8", 0
        ALIGN

; ======
; strlen
; ======

; entry: r1->string (\0 terminated)

; exit: r3 = len

strlen ROUT
        Push    "r1, lr"
        MOV     r3, #0
10
        LDRB    lr, [r1], #1
        TEQ     lr, #0
        ADDNE   r3, r3, #1
        BNE     %BT10
        Pull    "r1,pc",,^

; ======
; strcpy
; ======

; entry: r1->destination
;        r2->source (ctrl char terminated)

; exit:

strcpy ROUT
        Push    "r1,r2,lr"
10
        LDRB    lr, [r2], #1
        CMP     lr, #" "
        MOVLO   lr, #0
        STRB    lr, [r1], #1
        BHS     %BT10
        Pull    "r1,r2,pc",,^

        END
